package cn.iocoder.yudao.module.pay.order.dal.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.business.basic.dao.mapper.CoreMapper;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.api.pay.order.eums.UnifiedOrderStatusEnum;
import cn.iocoder.yudao.module.api.pay.order.eums.UnifiedPayChannelEnum;
import cn.iocoder.yudao.module.pay.order.dal.dataobject.PayOrderDO;
import cn.iocoder.yudao.module.pay.order.vo.PayOrderExportReqVO;
import cn.iocoder.yudao.module.pay.order.vo.PayOrderPageReqVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Nullable;
import org.apache.ibatis.annotations.Mapper;

import java.time.LocalDateTime;
import java.util.List;

@Mapper
public interface PayOrderMapper extends CoreMapper<PayOrderDO> {

    default PageResult<PayOrderDO> selectPage(PayOrderPageReqVO reqVO) {
        return selectPage(reqVO, new CoreLambdaQueryWrapper<PayOrderDO>()
                .eqIfPresent(PayOrderDO::getChannelCode, reqVO.getChannelCode())
                .likeIfPresent(PayOrderDO::getTradeNo, reqVO.getTradeNo())
                .likeIfPresent(PayOrderDO::getChannelOrderNo, reqVO.getChannelOrderNo())
                .eqIfPresent(PayOrderDO::getStatus, reqVO.getStatus())
                .betweenIfPresent(PayOrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(PayOrderDO::getId));
    }

    default List<PayOrderDO> selectList(PayOrderExportReqVO reqVO) {
        return selectList(new CoreLambdaQueryWrapper<PayOrderDO>()
                .eqIfPresent(PayOrderDO::getChannelCode, reqVO.getChannelCode())
                .likeIfPresent(PayOrderDO::getTradeNo, reqVO.getTradeNo())
                .likeIfPresent(PayOrderDO::getChannelOrderNo, reqVO.getChannelOrderNo())
                .eqIfPresent(PayOrderDO::getStatus, reqVO.getStatus())
                .betweenIfPresent(PayOrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(PayOrderDO::getId));
    }

    default PayOrderDO selectByNo(String no) {
        return selectOne(PayOrderDO::getNo, no);
    }

    default PayOrderDO selectByTradeNoAndStatus(String tradeNo, @Nullable Integer status) {
        CoreLambdaQueryWrapper<PayOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(PayOrderDO::getTradeNo, tradeNo);
        wrapper.eqIfPresent(PayOrderDO::getStatus, status);
        wrapper.orderByDesc(PayOrderDO::getId);
        return selectOne(wrapper);
    }

    default List<PayOrderDO> selectListByStatusAndGreaterThanCreateTime(Integer status, LocalDateTime minCreateTime) {
        return selectList(new LambdaQueryWrapper<PayOrderDO>()
                .eq(PayOrderDO::getStatus, status)
                .ge(PayOrderDO::getCreateTime, minCreateTime)
                .orderByDesc(PayOrderDO::getId));
    }

    default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) {
        return update(update, new LambdaQueryWrapper<PayOrderDO>()
                .eq(PayOrderDO::getId, id)
                .eq(PayOrderDO::getStatus, status));
    }

    default List<PayOrderDO> selectListByStatusAndLessThanExpireTime(Integer status, LocalDateTime expireTime) {
        return selectList(new LambdaQueryWrapper<PayOrderDO>()
                .eq(PayOrderDO::getStatus, status)
                .lt(PayOrderDO::getExpireTime, expireTime));
    }

    default List<String> selectPayNoByWeChatPayed(LocalDateTime minDateTime) {
        List<PayOrderDO> list = selectList(new LambdaQueryWrapper<PayOrderDO>()
                .eq(PayOrderDO::getStatus, UnifiedOrderStatusEnum.SUCCESS.getStatus())
                .in(PayOrderDO::getChannelCode, List.of(UnifiedPayChannelEnum.WX_LITE.getCode(), UnifiedPayChannelEnum.MALLBOOK_WX_LITE.getCode()))
                .gt(PayOrderDO::getSuccessTime, minDateTime)
                .select(PayOrderDO::getNo));
        if (CollUtil.isEmpty(list)) {
            return List.of();
        }
        return list.stream().map(PayOrderDO::getNo).toList();
    }

}
